package server

import (
	"common/config"
	"context"
	"errors"
	"gorm.io/gorm"
	"seckill/internal/models/dao"
	pb "seckill/proto"
	"time"
)

type Server struct {
	pb.UnimplementedSeckillServer
}

func (Server) CreateSecKill(ctx context.Context, request *pb.CreateSecKillRequest) (*pb.CreateSecKillResponse, error) {
	var sec dao.SecKill
	config.DB.Where("goods_name=?", request.GoodsName).Find(&sec).Limit(1)
	if sec.Id != 0 {
		return nil, errors.New("商品名称不能重复")
	}
	secKill := dao.SecKill{
		GoodsName:    request.GoodsName,
		SecKillPrice: float64(request.SecKillPrice),
		GoodsPrice:   float64(request.GoodsPrice),
		StartTime:    time.Now(),
		EndTime:      time.Now(),
		Stock:        int(request.Stock),
		SecKillType:  request.SecKillType,
	}
	err := config.DB.Create(&secKill).Error
	if err != nil {
		return nil, errors.New("创建失败")
	}
	return &pb.CreateSecKillResponse{Id: int64(secKill.Id)}, nil
}

func (Server) UpdateSecKill(ctx context.Context, request *pb.UpdateSecKillRequest) (*pb.UpdateSecKillResponse, error) {
	db := config.DB.Begin()
	var sec dao.SecKill
	db.Where("goods_name=?", request.GoodsName).Find(&sec).Limit(1)
	if sec.Id != 0 {
		return nil, errors.New("商品名称不能重复")
	}
	secKill := dao.SecKill{
		GoodsName:    request.GoodsName,
		SecKillPrice: float64(request.SecKillPrice),
		GoodsPrice:   float64(request.GoodsPrice),
		StartTime:    time.Now(),
		EndTime:      time.Now(),
		Stock:        int(request.Stock),
		SecKillType:  request.SecKillType,
	}
	err := db.Where("id=?", request.Id).Updates(&secKill).Error
	if err != nil {
		return nil, errors.New("创建失败")
	}
	return &pb.UpdateSecKillResponse{}, nil
}

func (Server) DeleteSecKill(ctx context.Context, request *pb.DeleteSecKillRequest) (*pb.DeleteSecKillResponse, error) {
	err := config.DB.Where("id=?", request.Id).Delete(&dao.SecKill{}).Error
	if err != nil {
		return nil, err
	}
	return &pb.DeleteSecKillResponse{}, nil
}

func (Server) SecKillList(ctx context.Context, request *pb.SecKillListRequest) (*pb.SecKillListResponse, error) {
	var sec []dao.SecKill
	config.DB.Scopes(Paginate(1, 15)).Find(&sec)
	var sli []*pb.SecKill
	for _, k := range sec {
		one := pb.SecKill{
			GoodsName:    k.GoodsName,
			SecKillPrice: float32(k.SecKillPrice),
			GoodsPrice:   float32(k.GoodsPrice),
			Stock:        int64(k.Stock),
			SecKillType:  k.SecKillType,
			StartTime:    k.StartTime.Unix(),
			EndTime:      k.EndTime.Unix(),
		}
		sli = append(sli, &one)
	}
	return &pb.SecKillListResponse{Seckill: sli}, nil
}

func Paginate(page, pageSize int) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if page <= 0 {
			page = 1
		}

		switch {
		case pageSize > 100:
			pageSize = 100
		case pageSize <= 0:
			pageSize = 10
		}

		offset := (page - 1) * pageSize
		return db.Offset(offset).Limit(pageSize)
	}
}

func (Server) TypeSecKill(ctx context.Context, request *pb.TypeSecKillRequest) (*pb.TypeSecKillResponse, error) {
	var sec []dao.SecKill
	config.DB.Where("sec_kill_type=?", request.Type).Find(&sec)
	return &pb.TypeSecKillResponse{Count: int64(len(sec))}, nil
}

func (Server) PriceSecKill(ctx context.Context, request *pb.PriceSecKillRequest) (*pb.PriceSecKillResponse, error) {
	var count int64
	var sec []dao.SecKill
	config.DB.Find(&sec)
	for _, k := range sec {
		if k.SecKillPrice > float64(request.StartPrice) && k.SecKillPrice < float64(request.EndPrice) {
			count++
		}
	}
	return &pb.PriceSecKillResponse{Count: count}, nil
}
